﻿using CMS6Tools.Common.TFS;
using CMS6Tools.TFSTasks.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.ProcessConfiguration.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace CMS6Tools.Management
{
    public partial class DailyTrackingForm : DockContent
    {

        const string StageFieldReferenceName = "Vision.Stage";
        const string CategoryFieldReferenceName = "Vision.Category";
        const string SeverityFieldReferenceName = "Microsoft.VSTS.Common.Severity";
        const string IterationPathFieldReferenceName = "System.IterationPath";
        const string ReleasePrefix = "Release ";
        const string TBDIterationName = "TBD";
        const string TicketCategory_Implementation = "Implementation";
        const string TicketCategory_Wireframe = "Wireframe";
        const string TicketCategory_Suggestion = "Suggestion";
        const string TagSourceCodeFolderath = "$/CMS 6/CMS 6/tags";
        readonly DateTime MinDateTime = new DateTime(2015, 1, 1);
        const float HoursAmount = 30.0F;

        public DailyTrackingForm()
        {
            InitializeComponent();
        }

        private void DailyTrackingForm_Load(object sender, EventArgs e)
        {

            //var tfsUrl = ConfigurationManager.AppSettings["codeChangeTfsDefaultCollectionURL"] ?? "http://andromeda:8080/tfs/CmsCollection";
            //var credential = CredentialCache.DefaultNetworkCredentials;
            //var tfsTeamProjectCollection = new TfsTeamProjectCollection(new Uri(tfsUrl), credential);

            //tfsTeamProjectCollection.EnsureAuthenticated();
            //if (tfsTeamProjectCollection.HasAuthenticated)
            //{
            //    AuthenticatedTfsTeamProjectCollection = tfsTeamProjectCollection; 
            //}
            //else
            //{
            //    AuthenticatedTfsTeamProjectCollection = null;
            //    MessageBox.Show("Authenticated failed.");
            //    return;
            //}

            var workItemStore = Util.AuthenticatedTfsTeamProjectCollection.GetService<WorkItemStore>();
            ProjectComboBox.ValueMember = "ID";
            ProjectComboBox.DisplayMember = "Name";
            ProjectComboBox.DataSource = workItemStore.Projects.OfType<Project>()
                //    .Select(a => new { 
                //    a.Name,
                //    a.Id,
                //    a.Uri
                //})
            .ToList();

            RunDailyTrack();
        }

        private void ProjectComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ProjectComboBox.SelectedIndex >= 0)
            {
                IterationTreeView.Nodes.Clear();
                var selectedProjectID = (int)((dynamic)ProjectComboBox.SelectedItem).Id;
                var workItemStore = Util.AuthenticatedTfsTeamProjectCollection.GetService<WorkItemStore>();
                var project = workItemStore.Projects.OfType<Project>().Where(a => a.Id == selectedProjectID).FirstOrDefault();
                if (project != null)
                {
                    var rootNodes = project.IterationRootNodes.OfType<Node>();
                    BindIterationTreeView(IterationTreeView.Nodes, rootNodes, true);
                    if (IterationTreeView.Nodes.Count > 0)
                        IterationTreeView.Nodes[0].EnsureVisible();
                }
            }
        }

        private void BindIterationTreeView(TreeNodeCollection treeNodeCollection, IEnumerable<Node> nodes, bool needCheckBox)
        {
            var teamService = Util.AuthenticatedTfsTeamProjectCollection.GetService<TfsTeamService>();
            var workItemStore = Util.AuthenticatedTfsTeamProjectCollection.GetService<WorkItemStore>();
            var commonStructureService = Util.AuthenticatedTfsTeamProjectCollection.GetService<ICommonStructureService4>();
            var configurationService = Util.AuthenticatedTfsTeamProjectCollection.GetService<TeamSettingsConfigurationService>();
            var versionControlService = Util.AuthenticatedTfsTeamProjectCollection.GetService<VersionControlServer>(); 

            foreach (var node in nodes.OrderByDescending(a => a.Name))
            {
                if (node.Name.Equals(TBDIterationName, StringComparison.InvariantCultureIgnoreCase))
                    continue;

                if (node.Name.StartsWith("Release 2014"))
                    continue;

                var childTreeNode = new TreeNode(node.Name);

                var iterationInfo = commonStructureService.GetNode(node.Uri.ToString());
                var hasStartDate = iterationInfo.StartDate.HasValue;
                var hasFinishDate = iterationInfo.FinishDate.HasValue;
                if (hasStartDate && hasFinishDate && iterationInfo.StartDate <= DateTime.Now && iterationInfo.FinishDate >= DateTime.Now)
                    childTreeNode.Checked = true;

                childTreeNode.Tag = node;
                treeNodeCollection.Add(childTreeNode);
                if (!needCheckBox)
                    HideCheckBox(IterationTreeView, childTreeNode);
                if (node.HasChildNodes)
                {
                    BindIterationTreeView(childTreeNode.Nodes, node.ChildNodes.OfType<Node>(), true);
                    childTreeNode.ExpandAll();
                }
            }
        }

        private const int TVIF_STATE = 0x8;
        private const int TVIS_STATEIMAGEMASK = 0xF000;
        private const int TV_FIRST = 0x1100;
        private const int TVM_SETITEM = TV_FIRST + 63;

        [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
        private struct TVITEM
        {
            public int mask;
            public IntPtr hItem;
            public int state;
            public int stateMask;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string lpszText;
            public int cchTextMax;
            public int iImage;
            public int iSelectedImage;
            public int cChildren;
            public IntPtr lParam;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam,
                                                 ref TVITEM lParam);

        /// <summary>
        /// Hides the checkbox for the specified node on a TreeView control.
        /// </summary>
        private void HideCheckBox(TreeView treeView, TreeNode node)
        {
            TVITEM tvi = new TVITEM();
            tvi.hItem = node.Handle;
            tvi.mask = TVIF_STATE;
            tvi.stateMask = TVIS_STATEIMAGEMASK;
            tvi.state = 0;
            SendMessage(treeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
        }

        private void DailyTrackButton_Click(object sender, EventArgs e)
        {
            RunDailyTrack();
        }

        private void RunDailyTrack()
        {
            var tfsEffortReportTask = new TfsEmptyTask(Util.AuthenticatedTfsTeamProjectCollection);

            var iterationNode = GetSelectIterationNodes(IterationTreeView.Nodes.OfType<TreeNode>()).FirstOrDefault(a => !a.HasChildNodes);
            DEVDataGridView.AutoGenerateColumns = true;
            if (iterationNode != null)
                DEVDataGridView.DataSource = tfsEffortReportTask.RunDailyTrackForDev(iterationNode);
        }

        private List<Node> GetSelectIterationNodes(IEnumerable<TreeNode> treeNodes)
        {
            var selectedNodes = new List<Node>();

            foreach (var treeNode in treeNodes)
            {
                if (treeNode.Checked)
                {
                    selectedNodes.Add(treeNode.Tag as Node);
                }
                if (treeNode.Nodes.Count > 0)
                {
                    selectedNodes.AddRange(GetSelectIterationNodes(treeNode.Nodes.OfType<TreeNode>()));
                }
            }

            return selectedNodes;
        }
    }

}
